/*
 * Simple test file for cxxomfort's
 * "get<type> from std::tuple" feature extension.
 *
 * Interfaces tested in this example:
 *
 * * std::tuple
 * * std::get<type>(std::tuple<...>)
 * * cxxomfort::type_name
 * * static_assert
 *
 */

#include <cxxomfort/cxxomfort.hpp>
#include <cxxomfort/tuple.hpp>
#include <cxxomfort/type_traits.hpp> // integral_constant
#include <cxxomfort/utility.hpp>
#include <cxxomfort/library/tuple.hpp>
#include <cxxomfort/library/type_name.hpp>
#include <iostream>

typedef std::tuple<long int, bool, std::string> TupleType;


template <typename TT>
typename std::enable_if<(std::tuple_size<TT>::value > 1), std::ostream&>::type
operator<< (std::ostream& os, TT const& tu) {
    using namespace std;
    os<< get<0>(tu)<< " ";
    os<< cxxomfort::library::tuple::tuple_shift(tu);
    return os;
}

template <typename TT>
typename std::enable_if<(std::tuple_size<TT>::value == 1), std::ostream&>::type
operator<< (std::ostream& os, TT const& tu) {
    using namespace std;
    return os<< get<0>(tu);
}


template <typename TT>
struct TTindexed
: public TT
{
    static_assert (cxxomfort::library::tuple::is_tuple<TT>::value, "TT must be a tuple<...> type.");

    //TTindexed (TT& p)
    //: tt(&p) {}
#if (CXXOMFORT_CXX_STD >= 2011)
    using TT::TT;

#else
    TTindexed (TT& t)
    : TT(t) {}

    template <typename A0, typename A1>
    TTindexed (A0 a0, A1 a1)
    : TT(a0,a1) {}

    template <typename A0, typename A1, typename A2>
    TTindexed (A0 a0, A1 a1, A2 a2)
    : TT(a0,a1,a2) {}

#endif

    //CXXO_CONSTEXPR explicit TTindexed (TT& tt) : TT(tt) {}

    template <unsigned I>
    typename std::tuple_element< I, TT >::type&
    operator[]
    (std::integral_constant<unsigned,I> const&) {
        using namespace std;
        return get<I>(*this) ;
    }

    template <unsigned I>
    typename std::tuple_element< I, TT >::type const&
    operator[]
    (std::integral_constant<unsigned,I> const&) const {
        return std::get<I>(*this) ;
    }

    private:
    //TT* const tt;

};

std::integral_constant<unsigned,0> I0c;
std::integral_constant<unsigned,1> I1c;
std::integral_constant<unsigned,2> I2c;
std::integral_constant<unsigned,3> I3c;


int main () {
    using namespace std;
    using namespace cxxomfort::library::tuple;

    cxxomfort::output_info(stdout);
    cout<< endl;

    cout<< cxxomfort::type_name<TupleType>()<< endl;

    TupleType tu1 (-7, false, string(4, 'h'));
    TTindexed<TupleType> ti1 (-7, true, string(7, 'p'));
    TTindexed<TupleType> tt1 ( tu1 );
    ti1[I0c]+= 107;
    ti1[I1c]= !ti1[I1c];

    cout<< (TupleType const&)(ti1)<< endl;

}



